package com.yuyou.fn.educational.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.wens.framework.service.impl.SuperServiceImpl;
import com.github.wens.mybatisplus.examples.Example;
import com.github.wens.mybatisplus.toolkit.IdWorker;
import com.github.wens.mybatisplus.toolkit.StringUtil;
import com.yuyou.fn.common.constant.ClassLevelEnum;
import com.yuyou.fn.common.exception.BusException;
import com.yuyou.fn.common.service.ISiteConfigService;
import com.yuyou.fn.common.util.*;
import com.yuyou.fn.educational.entity.*;
import com.yuyou.fn.educational.mapper.ExternalRegDetailMapper;
import com.yuyou.fn.educational.service.*;
import com.yuyou.fn.educational.vo.*;
import com.yuyou.fn.platform.entity.AreaTeam;
import com.yuyou.fn.platform.service.IAreaTeamService;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;

/**
 *
 * ExternalRegDetail 表数据服务层接口实现类
 *
 */
@Service
public class ExternalRegDetailServiceImpl extends SuperServiceImpl<ExternalRegDetailMapper, ExternalRegDetail,Long> implements IExternalRegDetailService {


    @Resource
    private IStudentService studentService;



    @Resource
    private IBaseSubjectService baseSubjectService;

    @Resource
    private ISiteConfigService siteConfigService;

    @Resource
    private RedisTemplate redisTemplate;

    /*层级转换关系，不在该层次 为不区分*/
    private Map<String,Integer> levelMap;

    private OkHttpClient client=OkHttpClientUtils.getIgnoreSsLClient(30,500);

    @Resource
    private IMemberStudentService memberStudentService;

    @PostConstruct
    public void initMap(){
        levelMap=new HashMap<>();
        levelMap.put("研习",ClassLevelEnum.核心素养班.ordinal());
        levelMap.put("卓越",ClassLevelEnum.核心素养班.ordinal());
        levelMap.put("创新",ClassLevelEnum.核心素养班.ordinal());
        levelMap.put("博学",ClassLevelEnum.新课标S班.ordinal());
        levelMap.put("励学",ClassLevelEnum.新课标A班.ordinal());
        levelMap.put("乐学",ClassLevelEnum.新课标B班.ordinal());
        levelMap.put("勤学",ClassLevelEnum.新课标B班.ordinal());
        levelMap.put("求学",ClassLevelEnum.新课标B班.ordinal());
    }

    private static final Logger log  = LoggerFactory.getLogger(ExternalRegDetailServiceImpl.class);


    public void importExternalReg(AreaTeam areaTeam,List<Period> periodList,List<BaseGrade> baseGradeList,List<ExternalRegDetailImportVo> externalRegDetaiImportVoList, String from) {
        if (externalRegDetaiImportVoList == null || externalRegDetaiImportVoList.size() <= 0 || StringUtils.isEmpty(from)) {
            return;
        }

        Set<String> classNos = new HashSet<>();
        Set<String> cids=new HashSet<>();
        for (ExternalRegDetailImportVo externalRegDetaiImportVo : externalRegDetaiImportVoList) {

            classNos.add(from + externalRegDetaiImportVo.getClassId());

            cids.add(externalRegDetaiImportVo.getMemberId());
        }
        Map<String, BaseGrade> baseGradeMap = BeanUtils.toMap(baseGradeList, "gradeName");
        List<BaseSubject> baseSubjectList = baseSubjectService.findAllFromCache();
        Map<String, BaseSubject> baseSubjectMap = BeanUtils.toMap(baseSubjectList, "subjectName");



        List<Student> studentList=studentService.findByCIDs(new ArrayList<>(cids));
        Map<String,Student> studentMapByCid=BeanUtils.toMap(studentList,"cid");


        for (ExternalRegDetailImportVo externalRegDetaiImportVo : externalRegDetaiImportVoList) {
            Long areaTeamId=areaTeam.getAreaTeamId();
            Long periodId = this.getPeriodIdByYearSeason(areaTeamId, periodList, externalRegDetaiImportVo.getYearName(), externalRegDetaiImportVo.getSeasonName());
            ExternalRegDetail externalRegDetail = new ExternalRegDetail();

            BaseGrade baseGrade = baseGradeMap.get(externalRegDetaiImportVo.getGradeName());
            BaseSubject baseSubject = baseSubjectMap.get(externalRegDetaiImportVo.getSubjectName());

            String cid=externalRegDetaiImportVo.getMemberId();

            externalRegDetail.setAreaTeamId(areaTeamId);
            externalRegDetail.setCampusNo(from + externalRegDetaiImportVo.getDeptId());
            externalRegDetail.setCampusName(externalRegDetaiImportVo.getDeptName());
            externalRegDetail.setPeriodId(periodId);
            externalRegDetail.setGradeId(baseGrade.getGradeId());
            externalRegDetail.setSubjectId(baseSubject.getSubjectId());
            externalRegDetail.setLevel(this.toLevel(from, externalRegDetaiImportVo.getGradationName()));
            externalRegDetail.setClassNo(from + externalRegDetaiImportVo.getClassId());
            externalRegDetail.setClassName(externalRegDetaiImportVo.getClassName());
            externalRegDetail.setStartAmount(Integer.parseInt(externalRegDetaiImportVo.getLessonStartNo()));
            externalRegDetail.setEndAmount(Integer.parseInt(externalRegDetaiImportVo.getLessonEndNo()));
            externalRegDetail.setLectureNum(externalRegDetail.getEndAmount() - externalRegDetail.getStartAmount() + 1);
            externalRegDetail.setFromId(from + externalRegDetaiImportVo.getRegId());
            if (StringUtils.isNotEmpty(externalRegDetaiImportVo.getCreateDate())) {
                externalRegDetail.setRegTime(Utils.parseDate(externalRegDetaiImportVo.getCreateDate(), "yyyy-MM-dd HH:mm:ss"));
            }
            if (StringUtils.isNotEmpty(externalRegDetaiImportVo.getSeniorId())) {
                externalRegDetail.setSeniorNo(from + externalRegDetaiImportVo.getSeniorId());
                externalRegDetail.setSeniorName(externalRegDetaiImportVo.getSeniorName());
            }
            externalRegDetail.setChargingStatus(this.toChargingStatus(from, externalRegDetaiImportVo.getRegState()));
            externalRegDetail.setRegStatus(this.toRegStatus(from, externalRegDetaiImportVo.getRegState()));
            externalRegDetail.setFromSource(from);
            externalRegDetail.setSeniorIdNo(externalRegDetaiImportVo.getSeniorIdcard());
            Student student = studentMapByCid.get(cid);
            if (student == null) {
                student = memberStudentService.selectByMemberIDNew(cid);
                if (student != null) {
                    student.setStudentNo(studentService.newStudentNo());
                    student.setStudentId(IdWorker.getId());
                    student.setRegClassAmount(0);
                    try {
                        studentService.insert(student);
                        studentMapByCid.put(cid, student);
                    } catch (Exception e) {
                        student = null;
                    }

                }
            }
            /*通过cid 查不到学生的话，该记录不做保存*/
            if (student==null){
                continue;
            }
            externalRegDetail.setStudentId(student.getStudentId());
            externalRegDetail.setStudentNo(student.getStudentNo());
            externalRegDetail.setStudentName(student.getName());
            externalRegDetail.setCreateTime(TimeUtils.now());
            externalRegDetail.setUpdateTime(TimeUtils.now());
            try {
                this.insert(externalRegDetail);
            } catch (Exception e) {
                this.updateByFromId(externalRegDetail,externalRegDetail.getFromId());
            }
        }
    }


    @Override
    public void updateByFromId(ExternalRegDetail externalRegDetail, String fromId) {
        Example<ExternalRegDetail> example=ExternalRegDetail.createExample();
        example.createCriteria().andEqualTo("fromId",fromId);
        this.updateSelectiveByExample(externalRegDetail,example);
    }

    @Override
    @Transactional
    public void  deleteByStudentNosClassNos(List<String> studentNos, List<String> classNos) {
        if (Utils.checkListEmpty(studentNos) || Utils.checkListEmpty(classNos)){
            return;
        }

        Example<ExternalRegDetail> externalRegDetailExample=ExternalRegDetail.createExample();
        externalRegDetailExample.createCriteria().andIn("studentNo",studentNos).andIn("classNo",classNos);
        deleteByExample(externalRegDetailExample);

    }

    public Integer toChargingStatus(String from,String regState){
        if ("zy".equals(from)){
            if ("1000".equals(regState) || "1001".equals(regState)){
                return 2;
            }
        }

        return 0;
    }

    /*集训 = 研习班；创新 = 核心素养班；状元、高端 = 新课标S班；精英 = 新课标A班；培优 = 新课标B班 （其他 = 不区分）*/
    public Integer toLevel(String from,String levelName){
        if ("zy".equals(from)){
            if (StringUtils.isNotEmpty(levelName)){
                levelName=levelName.substring(1,levelName.length());
                Integer level=levelMap.get(levelName);
                if (level==null){
                    level=ClassLevelEnum.不区分.ordinal();
                }
                return level;
            }
        }
        return null;
    }

    public Integer toRegStatus(String from,String regState){
        if ("zy".equals(from)){
            if ("1000".equals(regState) || "1001".equals(regState)){
                return 0;
            }else{
                return 4;
            }
        }
        return null;
    }

    public Long getPeriodIdByYearSeason(Long areaTeamId, List<Period> periodList, String year, String season){
        String periodName=(year+season).replace("班","");

        for (Period period:periodList){
            if (period.getAreaTeamId().equals(areaTeamId) && period.getPeriodName().equals(periodName)){
                return period.getPeriodId();
            }
        }
        return null;
    }
    public Long getAreaTeamIdByCity(List<AreaTeam> areaTeamList,String city){
        if (areaTeamList==null ){
            return null;
        }
        for (AreaTeam areaTeam:areaTeamList){
            if (areaTeam.getName().contains(city.replaceAll("市",""))){
                return areaTeam.getAreaTeamId();
            }
        }
        return null;
    }





    @Override
    public List<ExternalRegDetail> findByStudentIdPeriodIds(Long studentId, List<Long> periodIds, String... columns) {
        if (studentId==null || Utils.checkListEmpty(periodIds) ){
            return Collections.EMPTY_LIST;
        }
        Example<ExternalRegDetail> externalRegDetailExample=ExternalRegDetail.createExample();
        Example.Criteria criteria=externalRegDetailExample.createCriteria();
        criteria.andEqualTo("studentId",studentId);
        criteria.andIn("periodId",periodIds);
        criteria.andEqualTo("regStatus",0);
        if (columns!=null){
            externalRegDetailExample.selectProperties(columns);
        }
        return findListByExample(externalRegDetailExample);
    }

    @Override
    public List<ExternalRegDetail> findByStudentIdsPeriodIdsGradeId(List<Long> studentIds, List<Long> periodIds,Long gradeId, String... columns) {
        if (gradeId==null || Utils.checkListEmpty(studentIds)==null || Utils.checkListEmpty(periodIds) ){
            return Collections.EMPTY_LIST;
        }
        Example<ExternalRegDetail> externalRegDetailExample=ExternalRegDetail.createExample();
        Example.Criteria criteria=externalRegDetailExample.createCriteria();
        criteria.andIn("studentId",studentIds);
        criteria.andIn("periodId",periodIds);
        criteria.andEqualTo("regStatus",0);
        criteria.andEqualTo("gradeId",gradeId);
        if (columns!=null){
            externalRegDetailExample.selectProperties(columns);
        }
        return findListByExample(externalRegDetailExample);
    }

    @Override
    public List<ExternalRegDetail> findBySeniorIdNosPeriodIdsGradeId(Long areaTeamId,List<Long> periodIds, List<String> seniorIdNos, Long gradeId,String... columns) {
        if (gradeId==null || Utils.checkListEmpty(seniorIdNos) || Utils.checkListEmpty(periodIds) ){
            return Collections.EMPTY_LIST;
        }
        Example<ExternalRegDetail> externalRegDetailExample=ExternalRegDetail.createExample();
        Example.Criteria criteria=externalRegDetailExample.createCriteria();
        criteria.andIn("seniorIdNo",seniorIdNos);
        criteria.andIn("periodId",periodIds);
        criteria.andEqualTo("regStatus",0);
        criteria.andEqualTo("areaTeamId",areaTeamId);
        criteria.andEqualTo("gradeId",gradeId);
        if (columns!=null){
            externalRegDetailExample.selectProperties(columns);
        }
        return findListByExample(externalRegDetailExample);
    }

    @Override
    public void deleteByPeriodIdsGradeIds(List<Long> periodIds, List<Long> gradeIds) {
        if (Utils.checkListEmpty(periodIds) || Utils.checkListEmpty(gradeIds)){
            return;
        }
        Example<ExternalRegDetail> externalRegDetailExample=ExternalRegDetail.createExample();
        Example.Criteria criteria=externalRegDetailExample.createCriteria();
        criteria.andIn("periodId",periodIds);
        criteria.andIn("gradeId",gradeIds);
        this.deleteByExample(externalRegDetailExample);
    }

    @Override
    public long countByStudentIdPeriodIdsGradeIdsLevels(Long studentId, List<Long> periodIds, List<Long> gradeIds, List<Integer> levels) {
        Validate.notNull(studentId);
        Example<ExternalRegDetail> externalRegDetailExample=ExternalRegDetail.createExample();
        Example.Criteria criteria=externalRegDetailExample.createCriteria();
        criteria.andEqualTo("studentId",studentId);
        if(Utils.checkListNotEmpty(periodIds)){
            criteria.andIn("periodId",periodIds);
        }
        if(Utils.checkListNotEmpty(gradeIds)){
            criteria.andIn("gradeId",gradeIds);
        }
        if(Utils.checkListNotEmpty(periodIds)){
            criteria.andIn("level",levels);
        }
        return countByExample(externalRegDetailExample);
    }

    @Override
    public List<ExternalRegDetail> findPeriodRegList(Long periodId, ExternalRegQueryVo externalRegQueryVo, String ...columns) {
        if (periodId==null){
            return Collections.EMPTY_LIST;
        }
        Example<ExternalRegDetail> externalRegDetailExample=ExternalRegDetail.createExample();
        Example.Criteria criteria=externalRegDetailExample.createCriteria();
        criteria.andEqualTo("periodId",periodId);
        CriteriaUtils.fillCondition(criteria, externalRegQueryVo);
        if (columns!=null){
            externalRegDetailExample.selectProperties(columns);
        }
        return  this.findListByExample(externalRegDetailExample);
    }

    @Override
    public List<ExternalRegDetail> findPeriodsRegList(List<Long> periodIds, ExternalRegQueryVo externalRegQueryVo, String... columns) {
        if (Utils.isEmpty(periodIds)){
            return Collections.EMPTY_LIST;
        }
        Example<ExternalRegDetail> externalRegDetailExample=ExternalRegDetail.createExample();
        Example.Criteria criteria=externalRegDetailExample.createCriteria();
        criteria.andIn("periodId",periodIds);
        CriteriaUtils.fillCondition(criteria, externalRegQueryVo);
        if (columns!=null){
            externalRegDetailExample.selectProperties(columns);
        }
        return  this.findListByExample(externalRegDetailExample);
    }

    @Override
    public Long countPrevious(Long studentId, List<Long> periodIds, Long areaTeamId, Integer regStatus) {
        if (periodIds==null || periodIds.size()<=0  || studentId==null){
            return 0L;
        }
        Example<ExternalRegDetail> example = ExternalRegDetail.createExample();
        Example.Criteria criteria=example.createCriteria();
        criteria.andIn("periodId",periodIds);
        criteria.andEqualTo("studentId",studentId);
        criteria.andEqualTo("areaTeamId",areaTeamId);
        criteria.andEqualTo("regStatus",regStatus);
        return countByExample(example);
    }

    @Override
    public void findExternalReg(AreaTeam areaTeam, List<Period> periods, List<BaseGrade> baseGrades, String yearName, List<String> seasonNames, List<String> gradeNames) {
        String check = (String)redisTemplate.opsForHash().get( "regRecordQuery" , "tms");
        if (check!=null){
            throw new BusException("已有任务在同步，请耐心等待同步完成");
        }

        Threads.dispatch(new Runnable() {
            @Override
            public void run() {
                findZyExternalReg(areaTeam,periods,baseGrades,yearName,seasonNames,gradeNames);
            }
        });
    }

    @Override
    public void findZyExternalReg(AreaTeam areaTeam, List<Period> periods, List<BaseGrade> baseGrades, String yearName, List<String> seasonNames, List<String> gradeNames) {
        try {
            redisTemplate.opsForHash().put("regRecordQuery","tms","havingDeal");
            String token=this.getZyToken();
            this.dealZyExternalReg(areaTeam,periods,baseGrades,yearName,seasonNames,gradeNames,token);
        }catch (Exception e){
            throw new BusException(e.getMessage());
        }finally {
            redisTemplate.opsForHash().delete("regRecordQuery","tms");
        }

    }

    @Override
    public void dealZyExternalReg(AreaTeam areaTeam, List<Period> periods, List<BaseGrade> baseGrades, String yearName, List<String> seasonNames, List<String> gradeNames, String token) {
        String url=siteConfigService.findConfigValue("query_tms_student_reg");
        List<ExternalRegDetailImportVo> externalRegDetailImportVoList=new ArrayList<>();
        for (String seasonName:seasonNames){
            for (String gradeName:gradeNames){
                try{
                    externalRegDetailImportVoList.addAll(this.findExternalRegDetailImportList(url,token,yearName,seasonName,gradeName,"-2","-1"));
                }catch (Exception e){
                    throw new BusException(e.getMessage());
                }
            }
        }
        if (externalRegDetailImportVoList.size()>0){
            this.importExternalReg(areaTeam,periods,baseGrades,externalRegDetailImportVoList,"zy");
        }
    }

    @Override
    public String getZyToken() {
        String url  = siteConfigService.findConfigValue("login_tms_url");
        String token=null;
        try{
            token= ConnectTmsUtils.findToken(url);
            return token;
        }catch (Exception e){
            log.error("查询token失败",e);
            throw new BusException("查询token失败"+e.getMessage());
        }

    }

    @Override
    public List<ExternalRegDetailImportVo> findExternalRegDetailImportList(String url, String token, String yearName, String seasonName, String gradeName,String lastBegin, String begin) {
        if (Integer.parseInt(lastBegin)>=Integer.parseInt(begin)){
            return Collections.EMPTY_LIST;
        }
        List<ExternalRegDetailImportVo> externalRegDetailImportVoList=new ArrayList<>();

        TmsQueryVo tmsQueryVo=new TmsQueryVo();
        if (!"-1".equals(begin)){
            tmsQueryVo.setStartKey(begin);
        }
        tmsQueryVo.setSize(2000);
        TmsQueryDetailVo yearQueryVo = new TmsQueryDetailVo();
        yearQueryVo.setName("year_name");
        yearQueryVo.setValue(yearName);
        yearQueryVo.setOperation("equals");
        yearQueryVo.setType("string");
        TmsQueryDetailVo seasonQueryVo = new TmsQueryDetailVo();
        seasonQueryVo.setName("season_name");
        seasonQueryVo.setValue(seasonName);
        seasonQueryVo.setOperation("equals");
        seasonQueryVo.setType("string");
        TmsQueryDetailVo gradeQueryVo = new TmsQueryDetailVo();
        gradeQueryVo.setName("grade_name");
        gradeQueryVo.setValue(gradeName);
        gradeQueryVo.setOperation("equals");
        gradeQueryVo.setType("string");

        tmsQueryVo.setVariables(Arrays.asList(yearQueryVo,seasonQueryVo,gradeQueryVo));
        Request request = ConnectTmsUtils.getTmsRequest(url, JSONObject.toJSON(tmsQueryVo).toString(),token);
        try{
            Response response = client.newCall(request).execute();
            String result =response.body().string();
            JSONObject jsonObject=JSONObject.parseObject(result);
            String code=jsonObject.getString("code");
            String lastKey=jsonObject.getString("lastKey");
            if (!StringUtil.isNotEmpty(lastKey)){
                return Collections.EMPTY_LIST;
            }
            if ("200".equals(code)){
                String studentJson=jsonObject.getString("object");
                List<TmsRegMessage> tmsStudentMeassageList=JSONObject.parseArray(studentJson,TmsRegMessage.class);
                for (TmsRegMessage tmsRegMessage:tmsStudentMeassageList){
                    externalRegDetailImportVoList.add(tmsRegMessage.getColumns());
                }
                externalRegDetailImportVoList.addAll(this.findExternalRegDetailImportList(url,token,yearName,seasonName,gradeName,begin,lastKey));
            }
        }catch (Exception e){
            log.info(yearName+seasonName+gradeName+"起始位置"+begin+"查询失败:{}",e);
            throw new BusException(yearName+seasonName+gradeName+"起始位置"+begin+"查询失败:"+e.getMessage());
        }
        return externalRegDetailImportVoList;
    }

    @Override
    public List<ExternalRegDetail> findByAreaTeamIdPeriodIdsGradeId(Long areaTeamId, List<Long> periodIds,Long gradeId,String ...columns) {
        if (areaTeamId==null || Utils.checkListEmpty(periodIds) || gradeId==null ){
            return Collections.EMPTY_LIST;
        }
        Example<ExternalRegDetail> externalRegDetailExample=ExternalRegDetail.createExample();
        Example.Criteria criteria=externalRegDetailExample.createCriteria();
        criteria.andEqualTo("areaTeamId",areaTeamId);
        criteria.andIn("periodId",periodIds);
        criteria.andEqualTo("regStatus",0);
        criteria.andEqualTo("gradeId",gradeId);
        if (columns!=null){
            externalRegDetailExample.selectProperties(columns);
        }
        return findListByExample(externalRegDetailExample);
    }
}